function Airplane(start, end, startTime, elapsedTime){
  var self = this;
  this.map;
  this.followMe = false;
  this.id = Math.floor(Math.random() * 123456789);
  this.startTime = startTime;
  this.elapsedTime = elapsedTime;
  this.feature = false;
  this.from = start;
  this.to = end;
  this.sourceRouteFromAirport = [];
  this.routeFromAirport = [];
  this.routeForFlight = [];
  this.routeForDraw = [];
  this.routeMarkers = [];
  this.angleIndex = [];
  this.angleValue = [];
  this.currentAngle = false;
  this.speed = false;
  this.times = [];
  this.intervalId = false;
  this.position = 0;
  // czas symulacji (lotu) = (this.interval / 10) * Airplane.timeToXXX
  
  
  this.fly = function(route, isBeingFlight){
    this.sourceRouteFromAirport = route;
    if(isBeingFlight){ //do some
      this.calculateNewStartPoint();
      var originalTime = this.returnTime();
      var newTime = originalTime - (this.calculateTimeDiff() / 5);
      this.calculateTimes(newTime);
    }
    else{
      this.calculateTimes(false);
    }
    this.calculateRouteForFlight();
    var point = new OpenLayers.Geometry.Point(self.routeForFlight[0].lon, self.routeForFlight[0].lat);
		var angle = 0;
		switch(this.from){
			case "Paryz" : {
				angle = Airplane.defRunwayAngle[0];
				break;
			}
			case "Londyn" : {
				angle = Airplane.defRunwayAngle[1];
				break;
			}
			case "Berlin" : {
				angle = Airplane.defRunwayAngle[2];
				break;
			}
		}
    this.feature = new OpenLayers.Feature.Vector(point, {angle: angle});
    //this.feature = new OpenLayers.Feature.Vector(point);
    var layers = this.map.getLayersByName("Airplane Geometry");
    for(var i = 0; i < layers.length; i++){
      layers[i].addFeatures([this.feature]);
    }
    this.lastPoint = this.sourceRouteFromAirport[0];
    this.goAhead();
  }
  
  this.recalculateSim = function(){
    this.elapsedTime = newDateString;
    var index = 0;
    for(var i = 0; i < this.routeMarkers.length; i++){
      if(this.position < this.routeMarkers[i]){
        index = i
        this.routeFromAirport = this.sourceRouteFromAirport.slice();
        this.routeFromAirport.splice(0, index);
        this.routeFromAirport[0] = this.routeForFlight[this.position];
        break;
      }
      else if(this.position == this.routeMarkers[i]){
        index = i + 1;
        this.routeFromAirport = this.sourceRouteFromAirport.slice();
        this.routeFromAirport.splice(0, index);
        break;
      }
    }
    clearInterval(this.intervalId);
    if(document.getElementById(this.id)) document.getElementById("beingFlights").removeChild(document.getElementById(this.id));
    var originalTime = this.returnTime();
    var newTime = originalTime - (this.calculateTimeDiff() / 5);
    this.calculateTimes(newTime);
    this.calculateRouteForFlight();
    this.position = 0;
    this.goAhead();
  }
  
  this.goAhead = function(){
    var beingFlightsDiv = document.getElementById("beingFlights");
    var newParagraph = document.createElement('div');
    //newParagraph.setAttribute('onclick', 'setCenter('+self.id+')');
    newParagraph.setAttribute('id', self.id);
    //newParagraph.innerHTML = "<h3>" + "[" + this.from + "]->[" + this.to + "]->[" + this.startTime + "]" + "</h3>";
    newParagraph.innerHTML = "<h3><a href='#'>" + self.id + " " + this.from + "-" + this.to + "</a></h3>\
    <div>\
		<div>\
			start lotu: "+this.startTime+"<br/>\
			<a href='#' onclick='drawRoute("+self.id+")'>&rarr;pokaż trasę przelotu</a><br/>\
			<a href='#' onclick='setCenter("+self.id+")'>&rarr;podążaj za samolotem</a>\
		</div>\
	</div>";
    
    beingFlightsDiv.appendChild(newParagraph);
      this.intervalId = setInterval(function(){
        if(self.position < self.routeForFlight.length - 1){
          self.movoFromTo(self.routeForFlight[self.position], self.routeForFlight[self.position+1]);
          self.position++;
        }
        else{
          clearInterval(self.intervalId);
          beingFlightsDiv.removeChild(document.getElementById(self.id));
          if(self.routeForDraw.length > 0) self.drawRoute();
          self.feature.layer.removeFeatures(self.feature);
		  ///
		  $("#beingFlights").accordion('destroy');
		  $("#beingFlights").accordion({
 			header: 'h3',
	 		event: 'click',
		 	active: 0
		  });
		  ///
      for(var i = 0; i < airports.length; i++){
        for(var j = 0; j < airports[i].airplanes.length; j++){
          if(airports[i].airplanes[j].id == self.id){
            airports[i].airplanes.splice(j, 1);
          }
        }
      }
          delete self;
        }
      }, Airplane.interval);
    ///
    $("#beingFlights").accordion('destroy');
    $("#beingFlights").accordion({
		header: 'h3',
		event: 'click',
		active: 0
	});
	///
  }
  
  this.movoFromTo = function(from ,to){
    var angleToSet = 0, i, j, point, layers;
    this.feature.geometry.move(to.lon - from.lon, to.lat - from.lat);
    // -------------------
    if(this.currentAngle){
      angleToSet = this.currentAngle - Airplane.defImageAngle[0];
      this.feature.layer.removeFeatures(this.feature);
      this.feature = null;
      point = new OpenLayers.Geometry.Point(self.routeForFlight[self.position].lon, self.routeForFlight[self.position].lat);
      this.feature = new OpenLayers.Feature.Vector(point, {angle: angleToSet});
      layers = this.map.getLayersByName("Airplane Geometry");
      for(j = 0; j < layers.length; j++){
        layers[j].addFeatures([this.feature]);
      }
      this.currentAngle = false;
    }
    else{
      for(i = 0; i < this.angleIndex.length; i++){
        if(this.angleIndex[i] == this.position){
          angleToSet = this.angleValue[i+1] - Airplane.defImageAngle[0];
          this.feature.layer.removeFeatures(this.feature);
          this.feature = null;
          point = new OpenLayers.Geometry.Point(self.routeForFlight[self.position].lon, self.routeForFlight[self.position].lat);
          this.feature = new OpenLayers.Feature.Vector(point, {angle: angleToSet});
          layers = this.map.getLayersByName("Airplane Geometry");
          for(j = 0; j < layers.length; j++){
            layers[j].addFeatures([this.feature]);
          }
        }
      }
    }
    //-----------
    this.feature.layer.drawFeature(this.feature);
    if(this.followMe){
      if(document.getElementById("setCenterZoomLevel").value > 1 && document.getElementById("setCenterZoomLevel").value < 18){
        this.map.setCenter(from, document.getElementById("setCenterZoomLevel").value); // zależy od opcji w panelu
      }
      else this.map.setCenter(from, 12);
    }
  }
  
  this.calculateRouteForFlight = function(){
    var x, y, diff, abarray, step, angle;
    this.routeForFlight = [];
    this.routeMarkers = [];
    this.angleIndex = [];
    this.angleValue = [];
    if(this.routeFromAirport.length > 0){
      this.routeForFlight.push(this.routeFromAirport[0]);
      var count  = this.sourceRouteFromAirport.length - this.routeFromAirport.length;
      for(var d = 0; d < count; d++){
        this.routeMarkers[d] = 0;
      }
      for(var i = 0; i < this.times.length; i++){
        abarray = this.calculateLine(this.routeFromAirport[i], this.routeFromAirport[i+1]);
        diff = this.routeFromAirport[i+1].lon - this.routeFromAirport[i].lon;
        step = diff / (Math.floor(this.times[i]));
        for(var j = 0; j < (Math.floor(this.times[i])); j++){
          x = this.routeForFlight[this.routeForFlight.length - 1].lon + step;
          y = abarray[0] * x + abarray[1];
          this.routeForFlight.push(new OpenLayers.LonLat(x, y));
        }
        angle = this.calculateAngle([this.routeFromAirport[i], this.routeFromAirport[i+1]]);
        this.angleValue.push(angle);
        this.angleIndex.push(this.routeForFlight.length)
        this.routeMarkers.push(this.routeForFlight.length);
        if(!i) this.currentAngle = angle;
      }
    }
    else{
      this.routeForFlight.push(this.sourceRouteFromAirport[0]);
      for(var i = 0; i < this.times.length; i++){
        abarray = this.calculateLine(this.sourceRouteFromAirport[i], this.sourceRouteFromAirport[i+1]);
        diff = this.sourceRouteFromAirport[i+1].lon - this.sourceRouteFromAirport[i].lon;
        step = diff / (Math.floor(this.times[i]));
        for(var j = 0; j < (Math.floor(this.times[i])); j++){
          x = this.routeForFlight[this.routeForFlight.length - 1].lon + step;
          y = abarray[0] * x + abarray[1];
          this.routeForFlight.push(new OpenLayers.LonLat(x, y));
        }
        this.angleValue.push(this.calculateAngle([this.sourceRouteFromAirport[i], this.sourceRouteFromAirport[i+1]]));
        this.angleIndex.push(this.routeForFlight.length)
        this.routeMarkers.push(this.routeForFlight.length);
      }
    }
    this.step = step;
  }
  
  this.calculateLine = function(pointA, pointB){
    var x1, x2, y1, y2;
    x1 = pointA.lon;
    y1 = pointA.lat;
    x2 = pointB.lon;
    y2 = pointB.lat;
    
    var a, b;
    a = (y1 - y2) / (x1 - x2);
    b = (x1 * y2 - x2 * y1) / (x1 - x2);
    
    var array = [a, b];
    return array;
  }
  
  this.calculateTimes = function(changeTime){
    var distance, distanceFromTo, ratio, time, timeFromTo;
    distance = this.calculateDistance();
    this.times = [];
    if(changeTime){
      time = changeTime;
      for(var i = 0; i < this.routeFromAirport.length; i++){
      if(i < this.routeFromAirport.length - 1){
        distanceFromTo = this.calculateDistanceFromTo(this.routeFromAirport[i], this.routeFromAirport[i+1]);
        ratio = distanceFromTo / distance;
        timeFromTo = time * ratio;
        this.times.push(timeFromTo * 100);
      }
    }
    }
    else{
      time = this.returnTime();
      for(var i = 0; i < this.sourceRouteFromAirport.length; i++){
        if(i < this.sourceRouteFromAirport.length - 1){
          distanceFromTo = this.calculateDistanceFromTo(this.sourceRouteFromAirport[i], this.sourceRouteFromAirport[i+1]);
          ratio = distanceFromTo / distance;
          timeFromTo = time * ratio;
          this.times.push(timeFromTo * 100);
        }
      }
    }
  }
  
  this.calculateDistance = function(){
    var distance = 0;
    for(var i = 0; i < this.sourceRouteFromAirport.length; i++){
      if(i < this.sourceRouteFromAirport.length - 1){
        distance = distance + Math.pow((Math.pow(this.sourceRouteFromAirport[i+1].lon - this.sourceRouteFromAirport[i].lon, 2) + Math.pow(this.sourceRouteFromAirport[i+1].lat - this.sourceRouteFromAirport[i].lat, 2)), 1/2);
      }
    }
    return distance;
  }
  
  this.calculateAngle = function(line){
    var lineAB, tmpLine, distA, distB;
    var angle;
    //tmpLine = [line[0], line[0]];
    //lineAB = this.calculateLine(line[0], line[1]);
    x = line[0].lon - line[1].lon;
    y = line[0].lat - line[1].lat;
    // x > 0 - II lub III ćwiartka, else I lub IV
    // y > 0 - III lub IV, else I lub II
    if(x > 0){
      distA = line[0].lon - line[1].lon;
      if(y > 0){ // III
        distB = line[0].lat - line[1].lat;
        angle = 270 - (Math.atan(distB / distA) * 180 / Math.PI);
      }
      else{ // II
        distB = line[1].lat - line[0].lat;
        angle = 270 + (Math.atan(distB / distA) * 180 / Math.PI);
      }
    }
    else{
      distA = line[1].lon - line[0].lon;
      if(y > 0){ // IV
        distB = line[0].lat - line[1].lat;
        angle = 90 + (Math.atan(distB / distA) * 180 / Math.PI);
      }
      else{ // I
        distB = line[1].lat - line[0].lat;
        angle = 90 - (Math.atan(distB / distA) * 180 / Math.PI);
      }
    }
    //
    return angle;
  }
  
  this.calculateDistanceFromTo = function(from, to){
    var distance = 0;
    distance = distance + Math.pow((Math.pow(to.lon - from.lon, 2) + Math.pow(to.lat - from.lat, 2)), 1/2);
    return distance;
  }
  
  this.calculateSpeed = function(){
    var speed = 0;
    var distance = this.calculateDistance();
    var time = this.returnTime();
    speed = distance / time;
    return speed;
  }
  
  this.calculateY = function(x, pointA, pointB){
    var abarray = this.calculateLine(pointA, pointB);
    var y = abarray[0] * x + abarray[1];
    return y; 
  }
  
  this.calculateTimeDiff = function(){
    var startTimeArray = this.startTime.split(":");
    var elapsedTimeArray = this.elapsedTime.split(":");
    var today = new Date();
    var startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(),
                        parseInt(startTimeArray[0]), parseInt(startTimeArray[1]), today.getSeconds());
    var elapsedTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(),
                        parseInt(elapsedTimeArray[0]), parseInt(elapsedTimeArray[1]), today.getSeconds());
    var diff = Math.floor((elapsedTime - startTime) / 1000); //różnica w sekundach
    return diff / simSpeed;
  }
  
  this.calculateNewStartPoint = function(){
    if(this.sourceRouteFromAirport.length > 1){
      var distance = this.calculateDistance();
      var diff = this.calculateTimeDiff();
      var timeRatio = diff / (this.returnTime() * Airplane.interval / 10);
      var elapsedDistance = distance * timeRatio; // odległość, którą pokonał już samolot
      var searchedDistance = 0;
      var i = 0;
      while(searchedDistance < elapsedDistance){
        searchedDistance = searchedDistance + this.calculateDistanceFromTo(this.sourceRouteFromAirport[i], this.sourceRouteFromAirport[i+1]);
        i++;
      }
      var searchedDistanceLocal = this.calculateDistanceFromTo(this.sourceRouteFromAirport[i-1], this.sourceRouteFromAirport[i]);
      var elapsedDistanceLocal = 0;
      for(var j = 0; j < (i - 1); j++){
        elapsedDistanceLocal += this.calculateDistanceFromTo(this.sourceRouteFromAirport[j], this.sourceRouteFromAirport[j+1]);
      }
      elapsedDistanceLocal = elapsedDistance - elapsedDistanceLocal;
      i--;
      if(i > -1){
        this.routeFromAirport = this.sourceRouteFromAirport.slice();
        this.routeFromAirport.splice(0, i);
        var localRatio = elapsedDistanceLocal / searchedDistanceLocal;
        var newLon, newLat;
        if(this.routeFromAirport[1].lon < this.routeFromAirport[0].lon){
          newLon = Math.abs((this.routeFromAirport[0].lon - this.routeFromAirport[1].lon)) * (1 - localRatio) + this.routeFromAirport[1].lon;
        }
        else{
          newLon = Math.abs((this.routeFromAirport[1].lon - this.routeFromAirport[0].lon)) * localRatio + this.routeFromAirport[0].lon;
        }
        var abarray = this.calculateLine(this.routeFromAirport[0], this.routeFromAirport[1]);
        newLat = abarray[0] * newLon + abarray[1];
        this.routeFromAirport[0] = new OpenLayers.LonLat(newLon, newLat);
      }
    }
  }
  
  this.returnTime = function(){
    var time;
    switch(this.from){
      case "Paryz" : {
        switch(this.to){
          case "Londyn" : {
            time = Airplane.timeToLondon[0]; // z Paryża do Londynu (lon & lat / milisekundę)
            break;
          }
          case "Berlin" : {
            time = Airplane.timeToBerlin[0]; // z Paryża do Berlina (lon & lat / milisekundę)
            break;
          }
        }
        break;
      }
      case "Londyn" : {
        switch(this.to){
          case "Paryz" : {
            time = Airplane.timeToParis[0]; // z Londynu do Paryża (lon & lat / milisekundę)
            break;
          }
          case "Berlin" : {
            time = Airplane.timeToBerlin[1]; // z Londynu do Berlina (lon & lat / milisekundę)
            break;
          }
        }
        break;
      }
      case "Berlin" : {
        switch(this.to){
          case "Paryz" : {
            time = Airplane.timeToParis[1]; // z Berlina do Paryza (lon & lat / milisekundę)
            break;
          }
          case "Londyn" : {
            time = Airplane.timeToLondon[1]; // z Berlina do Londynu (lon & lat / milisekundę)
            break;
          }
        }
        break;
      }
    }
    return time;
  }

  this.drawRoute = function(){
    if(this.routeForDraw.length > 0){
      layers = this.map.getLayersByName("Simple Geometry");
      for(var j = 0; j < layers.length; j++){
        layers[j].removeFeatures(this.routeForDraw);
      }
      this.routeForDraw = [];
    }
    else{
      var feature;
      for(var i = 0; i < this.sourceRouteFromAirport.length - 1; i++){
        startPoint = new OpenLayers.Geometry.Point(this.sourceRouteFromAirport[i].lon, this.sourceRouteFromAirport[i].lat);
        endPoint = new OpenLayers.Geometry.Point(this.sourceRouteFromAirport[i+1].lon, this.sourceRouteFromAirport[i+1].lat);
        feature = new OpenLayers.Feature.Vector(
        new OpenLayers.Geometry.LineString([startPoint, endPoint]));
        this.routeForDraw.push(feature);
      }
      var layers = this.map.getLayersByName("Simple Geometry");
      for(var j = 0; j < layers.length; j++){
        layers[j].addFeatures(this.routeForDraw);
      }
    }
  }
}
// odświeżanie symulacji
Airplane.interval = 50;

// czasy przelotów (czas * Airplane.interval / 10 = czas symulacji), 1 jednostka = 5s
Airplane.timeToParis = [
  600, // z Londynu do Paryża
  1100 // z Berlina do Paryża
];
Airplane.timeToLondon = [
  600, // z Paryża do Londynu
  500 // z Berlina do Londynu
];
Airplane.timeToBerlin = [
  1200, // z Paryża do Berlina
  500 // z Londynu do Berlina
];

Airplane.defTimeToParis = [ 600, 1100 ];
Airplane.defTimeToLondon = [ 600, 500 ];
Airplane.defTimeToBerlin = [ 1200, 500 ];

Airplane.defImageAngle = [ -45 ];
Airplane.defRunwayAngle = [ -49, -45, 116 ];
